/***************************Encoding = UTF-8***********************************
 * RadarOnOLED
 * main.c
 * 
 * 
 * 教程链接： 
 * 
 * 适用于 VeriMake CH549DB 1.x.x
 * 主频：48MHz
 * -- by Merlin
*******************************************************************************/
#include <CH549_OLED.h>    
#include <CH549_UART.h> 
#include <CH549_SPI.h> 
#include <CH549_ADC.h>
#include <CH549_GPIO.h>
#include <CH549_DEBUG.h>
#include <CH549_sdcc.h>

#define Direction P0_6         //旋转方向
#define Steps P0_7             //转角步长
#define Clockwise 1            //顺时针
#define Counterclockwise 0     //逆时针

int oled_colum;
int oled_row;
void setCursor(int column,int row);       //声明函数


void UART1Init(UINT32 baudrate,UINT8 interrupt)
{
    SCON1 &= ~bU1SM0;                    //选择8位数据通讯
    SCON1 |= bU1SMOD;                    //快速模式
    SCON1 |= bU1REN;                     //使能接收
    SBAUD1 = 0 - FREQ_SYS/16/baudrate; //波特率配置
    SIF1 = bU1TI;                        //清空发送完成标志
	if(interrupt){                   //开启中断使能
		IE_UART1 = 1;
		EA = 1;
	}
}

typedef struct rada
{
	int x1Pos;
	int y1Pos;
	int dist1;
	int ang1;
	int x2Pos;
	int y2Pos;
	int dist2;
	int ang2;
	int x3Pos;
	int y3Pos;
	int dist3;
	int ang3;
	UINT8 checksum;
} RadarData;

//解析 XenP201S 的数据
UINT8 decode_XenP201S( char* buf,RadarData* radar){
	radar->x1Pos = (((int)buf[2]<<8)+buf[1]);
	radar->y1Pos = (((int)buf[4]<<8)+buf[3]);
	radar->dist1 = (((int)buf[6]<<8)+buf[5]);
	radar->ang1 = (((int)buf[8]<<8)+buf[7]);
	radar->ang1 = radar->ang1 / 10.0 - 90;

	radar->x2Pos = (((int)buf[10]<<8)+buf[9]);
	radar->y2Pos = (((int)buf[12]<<8)+buf[11]);
	radar->dist2 = (((int)buf[14]<<8)+buf[13]);
	radar->ang2 = (((int)buf[16]<<8)+buf[15]);
	radar->ang2 = radar->ang2 / 10.0 - 90;

	radar->x3Pos = (((int)buf[18]<<8)+buf[17]);
	radar->y3Pos = (((int)buf[20]<<8)+buf[19]);
	radar->dist3 = (((int)buf[22]<<8)+buf[21]);
	radar->ang3 = (((int)buf[24]<<8)+buf[23]);
	radar->ang3 = radar->ang3 / 10.0 - 90;

	return 0;
}

void LightTurn(BOOL Dir, UINT16 Deg)          //补光灯旋转
{
	GPIO_Init(PORT0,PIN6,MODE1);
	UINT16 STEP;
	STEP = Deg * 5 * 8 / 1.8;       //实际步长为角度/1.8，开的1/8档位，并且1:5减速
	Direction = Dir;
	setCursor(0,4);
	printf_fast_f("D:%d S:%3d G:%2d",Dir,STEP,Deg);
	for (UINT16 i = 0; i < STEP; i++)       //根据1s内调整旋转时间延迟
	{
		Steps = 1;
		mDelayuS(1000000/STEP);
		Steps = 0;
		mDelayuS(1000000/STEP);
	}
	
}

void FaceTrack( int A)           //捕获动作
{
	if ( A < 85)              //由于数据每1s都会不断跳动，保证在一定范围内固定补光
	{
		LightTurn(Counterclockwise, 1+(90-A)*5/9);
	}
	if ( A > 95)
	{
		LightTurn(Clockwise, 1+(A-90)*5/9);
	}	

}

volatile UINT8 recvBuf[30];
volatile UINT8 pBuf = 0;
volatile UINT8 fRecv = 0;

int xPos,yPos;
void main()
{
    CfgFsys( );           //CH549时钟选择配置
    mDelaymS(20);
	UART1Init(115200,1);
	// GPIO_Init(PORT0,PIN6,MODE1);
	
	SPIMasterModeSet(3);  //SPI主机模式设置，模式3
    SPI_CK_SET(4);       //设置SPI sclk 时钟信号分频
	OLED_Init();		  //初始化OLED  
	OLED_Clear();         //将OLED屏幕上内容清除
	setFontSize(8);      //设置文字大小

	OLED_Clear();
	setCursor(0,0);
	printf_fast_f("Radar");
	RadarData object;
	while(1){
		if(fRecv){
			fRecv = 0;		
			if (pBuf == 28){
				pBuf = 0;
				IE_UART1 = 0;
				setCursor(0,3);
				if(recvBuf[0]==0XAA && recvBuf[26]==0X55 && recvBuf[27]==0XCC){
//					RadarData object;
					decode_XenP201S(recvBuf,&object);										
					setCursor(0,0);
					printf_fast_f("X :%5d%5d%5d",object.x1Pos,object.x2Pos,object.x3Pos);
					setCursor(0,1);
					printf_fast_f("Y :%5d%5d%5d",object.y1Pos,object.y2Pos,object.y3Pos);
					setCursor(0,2);
					printf_fast_f("D :%5d%5d%5d",object.dist1,object.dist2,object.dist3);
					setCursor(0,3);
					printf_fast_f("A :%5d%5d%5d",object.ang1,object.ang2,object.ang3);
//					FaceTrack(object.ang1);
				}
				else{
					setCursor(0,0);
					printf_fast_f(" %x %x %x ",recvBuf[0],recvBuf[26],recvBuf[27]);
				}
				IE_UART1 = 1;
				FaceTrack(object.ang1);
			}
			if(recvBuf[0]!=0XAA){
				P2_2 = 0;
				pBuf=0;
			}else{
				P2_2 =1;
			}
		}
	}
}


/********************************************************************
* 函 数 名       : putchar
* 函数功能       : 将printf映射到OLED屏幕输出上
* 输    入      : 字符串
* 输    出    	: 字符串
********************************************************************/
int putchar( int a)
{      
    //在光标处显示文字 a
    OLED_ShowChar(oled_colum,oled_row,a);
    //将光标右移一个字的宽度,以显示下一个字
    oled_colum+=6;
    
    /*当此行不足以再显示一个字时，换行.
    同时光标回到最边(列坐标=0).
    */
    if (oled_colum>122){oled_colum=0;oled_row+=1;}
    return(a);
}

/********************************************************************
* 函 数 名       : setCursor
* 函数功能		   : 设置光标（printf到屏幕上的字符串起始位置）
* 输    入       : 行坐标 列坐标(此处一行为8个像素，一列为1个像素,所以屏幕上共有8行128列)
* 输    出    	 : 无
********************************************************************/
void setCursor(int column,int row)
{
    oled_colum = column;
    oled_row = row;
}

void UART1Interrupt(void) __interrupt INT_NO_UART1 __using 1 {
	pBuf%=28;
	recvBuf[pBuf] = CH549UART1RcvByte();
	pBuf++;
	fRecv = 1;
}